package com.kexio.common.excel;

import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

public final class ExcelExportUtils {

    private ExcelExportUtils() {}

    public static <T> void export(HttpServletResponse response,
                                  String filename,
                                  List<String> headers,
                                  List<String> fields,
                                  List<T> data) {
        try (Workbook wb = new XSSFWorkbook()) {
            Sheet sheet = wb.createSheet("Sheet1");
            int rowIdx = 0;
            // header
            Row header = sheet.createRow(rowIdx++);
            for (int i = 0; i < headers.size(); i++) {
                Cell cell = header.createCell(i);
                cell.setCellValue(headers.get(i));
            }
            // rows
            for (T item : data) {
                Row row = sheet.createRow(rowIdx++);
                Map<String, Object> map = toMap(item);
                for (int c = 0; c < fields.size(); c++) {
                    Object v = map.get(fields.get(c));
                    Cell cell = row.createCell(c);
                    cell.setCellValue(v == null ? "" : String.valueOf(v));
                }
            }
            // autosize
            for (int i = 0; i < headers.size(); i++) sheet.autoSizeColumn(i);

            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encoded + ".xlsx\"; filename*=UTF-8''" + encoded + ".xlsx");
            try (OutputStream os = response.getOutputStream()) {
                wb.write(os);
            }
        } catch (Exception e) {
            throw new RuntimeException("Excel export failed: " + e.getMessage(), e);
        }
    }

    @SuppressWarnings("unchecked")
    private static Map<String, Object> toMap(Object bean) {
        if (bean == null) return Collections.emptyMap();
        if (bean instanceof Map) {
            // 安全的类型转换，添加suppress warnings注解
            return (Map<String, Object>) bean;
        }
        Map<String, Object> map = new LinkedHashMap<>();
        try {
            for (PropertyDescriptor pd : Introspector.getBeanInfo(bean.getClass(), Object.class).getPropertyDescriptors()) {
                String name = pd.getName();
                Object val = pd.getReadMethod() != null ? pd.getReadMethod().invoke(bean) : null;
                map.put(name, val);
            }
        } catch (Exception ignored) {}
        return map;
    }
}
